#include "material.h"

/*
--------------------------------------------------------------------------------
http://msdn.microsoft.com/en-us/library/windows/desktop/bb147175(v=vs.85).aspx

Diffuse and ambient reflection work together to determine the perceived color of
an object, and are usually identical values.

Specular - Smaller values increase the area of the effect, creating a dull 
reflection that make the crystal look frosty. To make an object truly matte, 
set the Power member to zero and the color in Specular to black.
--------------------------------------------------------------------------------
*/

CMaterial::CMaterial() 
{
    /**
     * Constructor. Ensure that we initialise and obtain enough memory for
     * the material in memory.
     */
    ZeroMemory(&m_Material, sizeof(D3DMATERIAL9));
}

CMaterial::CMaterial(const D3DMATERIAL9 &material):
    m_Material(material)
{
    /**
     * Copy constructor. Creates a new CMaterial with the passed in material as 
     * the material.
     */
}



void CMaterial::setDiffuse(const D3DCOLORVALUE &color) 
{
    /**
     * Sets the diffuse colour of the material to the parameter passed.
     *
     * Diffuse reflection is greatest when the light strikes a vertex parallel 
     * to the vertex normal. As the angle increases, the effect of diffuse 
     * reflection diminishes. The amount of light reflected is the cosine of the
     * angle between the incoming light and the vertex normal.
     *
     * @param D3DCOLORVALUE color The color to assign to the diffuse.
     * 
     */
    m_Material.Diffuse = color;
}

void CMaterial::setDiffuse(float r, float g, float b, float a) 
{
   /*
    * Creates a new D3DCOLORVALUE with the 3 color parameters passed and then 
    * assigns the diffuse color to it.
    *
    * @param float r The red value to the new color.
    * @param float g The green value to the new color.
    * @param float b The blue value to the new color.
    * @param float a The alpga value to the new color.
    *
    */
    D3DCOLORVALUE color =  {r, g, b, a};
    m_Material.Diffuse = color;
}

void CMaterial::getDiffuse(float &r, float &g, float &b, float &a) const
{
    /**
     * Obtains the diffuse value of the material.
     *
     * @param float &r The reference to store the r value of the diffuse.
     * @param float &g The reference to store the g value of the diffuse.
     * @param float &b The reference to store the b value of the diffuse.
     * @param float &a The reference to store the a value of the diffuse.
     */
    r = m_Material.Diffuse.r;
    g = m_Material.Diffuse.g;
    b = m_Material.Diffuse.b;
    a = m_Material.Diffuse.a;
}

D3DCOLORVALUE CMaterial::getDiffuse() const
{
    /**
     * @return D3DCOLORVALUE The diffuse color of the material.
     */
    return m_Material.Diffuse;
}




void CMaterial::setAmbient(const D3DCOLORVALUE &color) 
{
    /**
     * Sets the ambient colour of the material to the parameter passed.
     *
     * Ambient reflection, like ambient light, is nondirectional. Ambient 
     * reflection has a lesser impact on the apparent color of a rendered 
     * object, but it does affect the overall color and is most noticeable when 
     * little or no diffuse light reflects off the material. 
     *
     * @param D3DCOLORVALUE color The color to assign to the ambient.
     * 
     */
    m_Material.Ambient= color;
}

void CMaterial::setAmbient(float r, float g, float b, float a) 
{
    /*
    * Creates a new D3DCOLORVALUE with the 3 color parameters passed and then 
    * assigns the ambient color to it.
    *
    * @param float r The red value to the new color.
    * @param float g The green value to the new color.
    * @param float b The blue value to the new color.
    * @param float a The alpga value to the new color.
    *
    */
    D3DCOLORVALUE color =  {r, g, b, a};
    m_Material.Ambient= color;
}

void CMaterial::getAmbient(float &r, float &g, float &b, float &a) const
{
    /**
     * Obtains the ambient value of the material.
     *
     * @param float &r The reference to store the r value of the ambient.
     * @param float &g The reference to store the g value of the ambient.
     * @param float &b The reference to store the b value of the ambient.
     * @param float &a The reference to store the a value of the ambient.
     */
    r = m_Material.Ambient.r;
    g = m_Material.Ambient.g;
    b = m_Material.Ambient.b;
    a = m_Material.Ambient.a;
}

D3DCOLORVALUE CMaterial::getAmbient() const
{
    /**
     * @return D3DCOLORVALUE The ambient color of the material.
     */
    return m_Material.Ambient;
}



void CMaterial::setSpecular(const D3DCOLORVALUE &color) 
{
    /**
     * Sets the specular colour of the material to the parameter passed.
     *
     * Specular reflection creates highlights on objects, making them appear 
     * shiny.  You establish the color of the specular highlights by setting the
     * Specular member to the desired RGBA color - the most common colors are 
     * white or light gray. The values you set in the Power member control how 
     * sharp the specular effects are.
     *
     * @param D3DCOLORVALUE color The color to assign to the specular.
     * 
     */
    m_Material.Specular = color;
}

void CMaterial::setSpecular(float r, float g, float b, float a) 
{
    /*
    * Creates a new D3DCOLORVALUE with the 3 color parameters passed and then 
    * assigns the specular color to it.
    *
    * @param float r The red value to the new color.
    * @param float g The green value to the new color.
    * @param float b The blue value to the new color.
    * @param float a The alpga value to the new color.
    *
    */
    D3DCOLORVALUE color =  {r, g, b, a};
    m_Material.Specular = color;
}

void CMaterial::getSpecular(float &r, float &g, float &b, float &a) const
{
    /**
     * Obtains the specular value of the material.
     *
     * @param float &r The reference to store the r value of the specular.
     * @param float &g The reference to store the g value of the specular.
     * @param float &b The reference to store the b value of the specular.
     * @param float &a The reference to store the a value of the specular.
     */
    r = m_Material.Specular.r;
    g = m_Material.Specular.g;
    b = m_Material.Specular.b;
    a = m_Material.Specular.a;
}

D3DCOLORVALUE CMaterial::getSpecular() const
{
    /**
     * @return D3DCOLORVALUE The specular color of the material.
     */
    return m_Material.Specular;
}




void CMaterial::setEmissive(const D3DCOLORVALUE &color) 
{
    /**
     * Sets the emissive colour of the material to the parameter passed.
     *
     * Materials can be used to make a rendered object appear to be 
     * self-luminous.
     *
     * @param D3DCOLORVALUE color The color to assign to the emissive Materials.
     * 
     * 
     */
    m_Material.Emissive = color;
}

void CMaterial::setEmissive(float r, float g, float b, float a) 
{
    /*
    * Creates a new D3DCOLORVALUE with the 3 color parameters passed and then 
    * assigns the emissive color to it.
    *
    * @param float r The red value to the new color.
    * @param float g The green value to the new color.
    * @param float b The blue value to the new color.
    * @param float a The alpga value to the new color.
    *
    */
    D3DCOLORVALUE color =  {r, g, b, a};
    m_Material.Emissive = color;
}

void CMaterial::getEmissive(float &r, float &g, float &b, float &a) const
{
    /**
     * Obtains the emissive value of the material.
     *
     * @param float &r The reference to store the r value of the emssive.
     * @param float &g The reference to store the g value of the emssive.
     * @param float &b The reference to store the b value of the emssive.
     * @param float &a The reference to store the a value of the emssive.
     */
    r = m_Material.Emissive.r;
    g = m_Material.Emissive.g;
    b = m_Material.Emissive.b;
    a = m_Material.Emissive.a;
}

D3DCOLORVALUE CMaterial::getSEmissive() const
{
    /**
     * @return D3DCOLORVALUE The emissive color of the material.
     */
    return m_Material.Emissive;
}




void CMaterial::setPower(float power) 
{
    /**
     * Sets the emissive colour of the material to the parameter passed.
     *
     * the values you set in the Power member control how sharp the specular 
     * effects are.
     *
     * @param float power The power to assign to power.
     * 
     */
   
    m_Material.Power = power;
}

float CMaterial::getPower()
{
    /**
     * @return float The intensity of the material.
     */
    return m_Material.Power;
}



void CMaterial::applyMaterial(LPDIRECT3DDEVICE9 p_Device) const 
{
     /**
     * Sets the material to the active material on the given device 
     *
     * @param LPDIRECT3DDEVICE9 p_Device The device to be used.
     */
    p_Device ->SetMaterial(&m_Material);
}